package com.boot.service;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSON;
import com.boot.business.PurchaseDTO;
import com.boot.exception.BusinessException;
import com.boot.feign.OrderFeign;
import com.boot.feign.StorageFeign;
import com.boot.feign.UserFeign;
import com.boot.result.Result;
import com.boot.user.dto.DeduceDTO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.seata.spring.annotation.GlobalTransactional;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

@Service
@Slf4j
public class BusinessService {
    private StorageFeign storageFeign;
    private OrderFeign orderFeign;
    private UserFeign userFeign;
    private RabbitTemplate rabbitTemplate;


    public BusinessService(StorageFeign storageFeign, OrderFeign orderFeign, UserFeign userFeign, RabbitTemplate rabbitTemplate) {
        this.storageFeign = storageFeign;
        this.orderFeign = orderFeign;
        this.userFeign = userFeign;
        this.rabbitTemplate = rabbitTemplate;
    }

    @Value("${business.mq.order-fallback-exchange}")
    private String orderExchange;

    @Value("${business.mq.routing-key}")
    private String routingKey;

    @GlobalTransactional(rollbackFor = Exception.class)
    @SentinelResource(value = "createOrder",  blockHandler = "handleFlowLimit",fallback = "handleError")
    public Result purchaseOrder(PurchaseDTO purchaseDTO) {
        //1.扣减库存
        Result deductResult = storageFeign.deduct(purchaseDTO);
        if (deductResult.getCode() != 200) {
            throw new BusinessException(deductResult.getMessage());
        }
        BigDecimal totalAmount = BigDecimal.valueOf((Integer) deductResult.getData());
        purchaseDTO.setTotalAmount(totalAmount);
        //2.创建订单

        Result createOrderResult = orderFeign.createOrder(purchaseDTO);
        if (createOrderResult.getCode() != 200) {
            throw new BusinessException(createOrderResult.getMessage());
        }
        //3.扣减用户余额
        DeduceDTO deduceDTO = new DeduceDTO();
        deduceDTO.setUserId(purchaseDTO.getUserId());
        deduceDTO.setAmount(totalAmount);
        Result deduceResult = userFeign.deduce(deduceDTO);
        if (deduceResult.getCode() != 200) {
            throw new BusinessException(deductResult.getMessage());
        }
        return Result.success(createOrderResult.getData());
    }

    // 流控降级
    public Result handleFlowLimit(PurchaseDTO purchaseDTO, BlockException e) {
        log.warn("触发流控，订单进入队列：{}",  purchaseDTO.getProductId());
        // 构建延迟消息（假设使用插件实现延迟队列）
        Message message = MessageBuilder.withBody(JSON.toJSONBytes(purchaseDTO))
                .setHeader("x-delay", 5000)  //5s后处理
                .build();
        // 发送到MQ
        rabbitTemplate.convertAndSend(orderExchange, routingKey, message, m -> {
            m.getMessageProperties().setDelayLong(5000L);
            return m;
        });

        return Result.build(50001, "订单进入队列，请稍后查看", null);
    }
    // 系统异常降级
    public Result handleError(PurchaseDTO purchaseDTO, Throwable e) {
        log.error("订单处理异常：{}", e.getMessage());
        return Result.build(50002, "订单处理异常", null);
    }

}
